
`ifndef ID_V
`define ID_V


`include "defines.v"

module id(
	//from instf_id
	input  wire[`InstAddrWidth - 1 : 0] inst_addr_i,
	input  wire[`InstWidth - 1 : 0] 	inst_i,
	
	// to regs 
	output reg[`RegAddrWidth - 1 : 0] 	reg1_raddr_o,
	output reg[`RegAddrWidth - 1 : 0] 	reg2_raddr_o,
	// from regs
	input  wire[`RegDataWidth - 1 : 0] 	reg1_rdata_i,
	input  wire[`RegDataWidth - 1 : 0] 	reg2_rdata_i,
	
	//to id_ex
	output reg[`InstAddrWidth - 1 : 0] 	inst_addr_o,
	output reg[`InstWidth - 1 : 0] 		inst_o,
	output reg[`RegAddrWidth - 1 : 0]  	reg_waddr_o,	
	output reg 		 					reg_wen_o,
	// output reg[`RegDataWidth - 1 : 0] reg1_rdata_o,
	// output reg[`RegDataWidth - 1 : 0] reg2_rdata_o,
	output reg[`OPWidth - 1 : 0] 		op1_o,	
	output reg[`OPWidth - 1 : 0] 		op2_o
	
);

wire[6:0] opcode; 
wire[2:0] funct3;
wire[6:0] funct7;
wire[4:0] rd	; 
wire[4:0] rs1	;
wire[4:0] rs2	;
	
assign opcode = inst_i[6:0];
assign funct3 = inst_i[14:12];
assign funct7 = inst_i[31:25];
assign rd 	  = inst_i[11:7];
assign rs1 	  = inst_i[19:15];
assign rs2 	  = inst_i[24:20];

always @(*)begin
	inst_o  	= inst_i;
	inst_addr_o = inst_addr_i;  
	// reg1_rdata_o = reg1_rdata_i;
	// reg2_rdata_o = reg2_rdata_i;
	
	case(opcode)
		`INST_TYPE_R : begin
			case(funct3)
				`INST_ADD, `INST_SUB : begin
					reg1_raddr_o 	= rs1;
					reg2_raddr_o 	= rs2;
					op1_o 	   		= reg1_rdata_i;
					op2_o      		= reg2_rdata_i;
					reg_waddr_o  	= rd;
					reg_wen_o    	= 1'b1;
				end

				default : begin
					reg1_raddr_o 	= `REG_X0_ADDR;
					reg2_raddr_o 	= `REG_X0_ADDR;
					op1_o 	   		= `OP_ZERO;
					op2_o      		= `OP_ZERO;
					reg_waddr_o  	= `REG_X0_ADDR;
					reg_wen_o    	= 1'b0;			
				end
			endcase				
		end

		`INST_TYPE_I : begin
			case(funct3)
				`INST_ADDI : begin
					reg1_raddr_o 	= rs1;
					reg2_raddr_o 	= `REG_X0_ADDR;
					op1_o 	   		= reg1_rdata_i;
					op2_o      		= {{20{inst_i[31]}}, inst_i[31:20]};
					reg_waddr_o  	= rd;
					reg_wen_o    	= 1'b1;
				end

				default : begin
					reg1_raddr_o 	= `REG_X0_ADDR;
					reg2_raddr_o 	= `REG_X0_ADDR;
					op1_o 	   		= `OP_ZERO;
					op2_o      		= `OP_ZERO;
					reg_waddr_o  	= `REG_X0_ADDR;
					reg_wen_o    	= 1'b0;				
				end
			endcase	
		end
		
		`INST_TYPE_SB : begin
			case(funct3)
				`INST_BNE,`INST_BEQ : begin
					reg1_raddr_o 	= rs1;
					reg2_raddr_o 	= rs2;
					op1_o 	   		= reg1_rdata_i;
					op2_o      		= reg2_rdata_i;
					reg_waddr_o  	= `REG_X0_ADDR;
					reg_wen_o    	= 1'b0;						
				end

				default : begin
					reg1_raddr_o 	= `REG_X0_ADDR;
					reg2_raddr_o 	= `REG_X0_ADDR;
					op1_o 	   		= `OP_ZERO;
					op2_o      		= `OP_ZERO;
					reg_waddr_o  	= `REG_X0_ADDR;
					reg_wen_o    	= 1'b0;							
				end
			endcase
		end

		`INST_JAL : begin
			reg1_raddr_o 	= `REG_X0_ADDR;
			reg2_raddr_o 	= `REG_X0_ADDR;
			op1_o 	   		= {{11{inst_i[31]}}, inst_i[31], inst_i[19:12], inst_i[20], inst_i[30:21], 1'b0};
			op2_o      		= `OP_ZERO;
			reg_waddr_o  	= rd;
			reg_wen_o    	= 1'b1;					
		end

		`INST_LUI : begin
			reg1_raddr_o 	= `REG_X0_ADDR;
			reg2_raddr_o 	= `REG_X0_ADDR;
			op1_o 	   		= {inst_i[31:12], 12'b0};
			op2_o      		= `OP_ZERO;
			reg_waddr_o  	= rd;
			reg_wen_o    	= 1'b1;				
		end

		default : begin
			reg1_raddr_o 	= `REG_X0_ADDR;
			reg2_raddr_o 	= `REG_X0_ADDR;
			op1_o 	   		= `OP_ZERO;
			op2_o      		= `OP_ZERO;
			reg_waddr_o  	= `REG_X0_ADDR;
			reg_wen_o    	= 1'b0;					
		end
	endcase
end

endmodule


`endif // ID_V